package wcg;

import ikelib.MapUtil;
import ikelib.NumericTextField;

import javax.swing.JPanel;

import java.awt.Component;
import java.awt.Desktop;
import java.awt.Frame;
import java.awt.BorderLayout;
import java.awt.Point;

import javax.swing.JDialog;
import java.awt.Dimension;
import javax.swing.JButton;
import java.awt.Rectangle;

import javax.swing.ImageIcon;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPopupMenu;
import javax.swing.JScrollBar;
import javax.swing.KeyStroke;
import javax.swing.ListSelectionModel;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;

import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLEncoder;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.TreeSet;

import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.border.EtchedBorder;
import javax.swing.border.TitledBorder;
import javax.swing.filechooser.FileNameExtensionFilter;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;

import java.awt.GridBagConstraints;
import javax.swing.BoxLayout;
import javax.swing.JLabel;
import javax.swing.JComboBox;
import javax.swing.JTextField;

import GraphicView.GraphicView;
import javax.swing.JMenuBar;
import javax.swing.JMenu;
import java.awt.Insets;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import javax.swing.event.MenuListener;
import javax.swing.event.MenuEvent;

//---------------------------------------------------------------------------
// Time-Chart  の表示プロパティを設定する
//
public class DialogChannelDisplayProperty extends JDialog implements MouseListener,ActionListener,ItemListener  {
	
	//----------------------------------------------------------------
		// Cell Renderer
	public class DoubleRenderer extends DefaultTableCellRenderer {

		public DoubleRenderer() {
			super();
			setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
		}

		public void setValue(Object value) {
			if ((value != null) && (value instanceof Number)) {
				Number numberValue = (Number) value;
				//NumberFormat formatter = NumberFormat.getInstance();
				//   value = formatter.format(numberValue.doubleValue());
				value = String.format("%g",numberValue.doubleValue());
			} 
			super.setValue(value);
		} 

	} 
	//------------------------------------------------------
	//　テーブルモデル
	public class CustomTableModel extends DefaultTableModel {
		private static final long serialVersionUID = 1L;
	    CustomTableModel(Object[][] tableData, String[] tableColumnName) {
			super(tableData,tableColumnName);
		}

		public Class<?> getColumnClass(int col){
			return TableData[0][col].getClass();
	    }

	}
	private static final long serialVersionUID = 1L;
	private  int Mode = 0; // 0: for display config  1: view
	private  GraphicView Parent = null; //@
	public JButton jButtonOK = null;
	public JButton jButtonCANCEL = null;
	private JPanel jContentPane = null;
	private JScrollPane jScrollPaneTable = null;
	private JTable jTableDisplayProperty = null;
	private String[] TableColumnName = {"Index","IndexSub","Channel","Station","Component","Display","Mask","PhysicalQuantity","Factor","Unit","FullScale",
			"Latitude","Longitude","Altitude"};
//	private Object[] TableData = {
//			new Integer(0),new Integer(0),new Integer(0),new String(""),new String(""),new Boolean(false),new Boolean(false),new Float(0.0),new String(""),new Long(0L)
//	};
	//public JDialog ThisDialog=null; // @
	
	private Object[][] TableData = {
			{new Integer(0),new Integer(0),new Integer(0),new String(""),new String(""),new Boolean(false),new Boolean(false),new Boolean(false),new Double(0.0),new String(""),new Long(0L),
					new Double(0.0),new Double(0.0),new Double(0.0)}
			
	};
	private CustomTableModel TableModel=null;//@
	private JPopupMenu PopupMenu=null;
	//private HashMap<Integer, Integer> ChanneDisplayMap;  //  @jve:decl-index=0:
	private JPanel jPanelSouth = null;
	
	public String ChannelTableFileFolder = new String("");  //  @jve:decl-index=0:
	public String ChannelTableFilePath = new String("");  //  @jve:decl-index=0:
	public ArrayList<String[]> ChannelTable = new ArrayList<String[]>();  //  @jve:decl-index=0:
	
	private Point MouseClickPoint = new Point();  //  @jve:decl-index=0:
	private JLabel jLabelAllSetReset = null;
	private JLabel jLabelSelectSetReset = null;
	private JLabel jLabelSelectCalculator = null;
	private NumericTextField jTextFieldCalculator = null;
	
	// コピーペーストを実装するために
	private final static KeyStroke CUT
	= KeyStroke.getKeyStroke(KeyEvent.VK_X,ActionEvent.CTRL_MASK,false);

	private final static KeyStroke COPY 
	= KeyStroke.getKeyStroke(KeyEvent.VK_C,ActionEvent.CTRL_MASK,false);

	private final static KeyStroke PASTE 
	= KeyStroke.getKeyStroke(KeyEvent.VK_V,ActionEvent.CTRL_MASK,false);

	
	
	public void setMode(int mode){
		Mode = mode;
		if(Mode==1) setTitle("All channels (channel.ini) ");
		else if(Mode==0) setTitle("Displayed channels only");
	}
	public int getMode(){
		return Mode;
	}
	// popup メニュー
	private JMenuItem addPopupMenuItem(JPopupMenu popup,String name, ActionListener al) {
		JMenuItem item = new JMenuItem(name); // @
		item.addActionListener(al);
		popup.add(item);
		return item;
	}
	private JMenuItem addPopupMenuItem(JPopupMenu popup,String name, ActionListener al,ImageIcon icon) {
		JMenuItem item = addPopupMenuItem(popup,name,al);//@
		item.setIcon(icon);
		return item;
	}
	/**
	 * 選択されたセル（boolean)をセット、リセットする
	 * @param set
	 */
	private void setSelectedItemSet(boolean set){
		int col[] = jTableDisplayProperty.getSelectedColumns();
		for(int i=0;i<col.length;i++){
			int row[] = jTableDisplayProperty.getSelectedRows();
			if(jTableDisplayProperty.getValueAt(row[0], col[i]) instanceof Boolean){
				for(int j=0;j<row.length;j++){
					if(set )		jTableDisplayProperty.setValueAt(true,row[j],col[i]);
					else if(!set)	jTableDisplayProperty.setValueAt(false,row[j],col[i]);
				}
			}
		}
	}
	// 
	/**
	 * 指定されたcolumn をすべてセット、リセットする
	 * @param set セットするかどうか
	 * @param column　カラムの文字
	 */
	private void setAllItemSet(boolean set,String column){
		int col = getColumnFromName(column);
		col = jTableDisplayProperty.convertColumnIndexToView(col);
		for(int i=0;i<jTableDisplayProperty.getRowCount();i++){
			if(jTableDisplayProperty.getValueAt(i, col) instanceof Boolean){
				if(set )		jTableDisplayProperty.setValueAt(true,i,col);
				else if(!set)	jTableDisplayProperty.setValueAt(false,i,col);
			}
		}
	}
	
	/**
	 * 指定されたパターンでセット、リセットする
	 * @param colname カラムの名前
	 * @param num　　　 (equal && ch == num) || (!equal && ch!=num)のとき　setする
	 * @param equal
	 * @param set
	 */
	private void setMaskSpecialPattern(String colname,int num,boolean equal,boolean set){
		int col = getColumnFromName(colname);
		int chcol = getColumnFromName("Channel");
		col = jTableDisplayProperty.convertColumnIndexToView(col);
		for(int i=0;i<jTableDisplayProperty.getRowCount();i++){
			int ch = Integer.valueOf(jTableDisplayProperty.getValueAt(i, chcol).toString(),16);
			ch &= 0x0f;
			if((equal && ch == num) || (!equal && ch!=num)){
				if(jTableDisplayProperty.getValueAt(i, col) instanceof Boolean){
					if(set )		jTableDisplayProperty.setValueAt(true,i,col);
					else if(!set)	jTableDisplayProperty.setValueAt(false,i,col);
				}
			}
		}
	}

	/**
	 * @param owner
	 */
	public DialogChannelDisplayProperty(Frame owner) {
		super(owner);
		initialize();
		dlgFactor = new DialogFactor(owner);
		//ThisDialog=this; // @
	}
	/**
	 * parent　のセット
	 * @param owner
	 */
	public void setParent(GraphicView owner) {
		Parent = owner; // @
	}
	/**
	 * This method initializes this
	 * 
	 * @return void
	 */
	private void initialize() {
		this.setSize(793, 401);
		this.setTitle("Channel Configuration");
		this.setContentPane(getJContentPane());
	}
	/**
	 * テーブルの全クリア
	 */
	private void clearTable(boolean confirm){
		
		int max = TableModel.getRowCount();
		if(max>=1){
			if(!confirm || JOptionPane.YES_OPTION == JOptionPane.showConfirmDialog(this, "Clear ALL table value ? ","Confirmation",JOptionPane.YES_NO_OPTION)){
				for(int i=0;i<max;i++){
					TableModel.removeRow(0);
				}
			}
		}
	}
	// --------------------
	// データをセットする。
	public void setData(int[] ch,boolean[] disp,boolean[] pu,String[] station,String[] component,int[] tblindex,double[] factor,String[] unit,long[] fullscale,
			boolean[] mask,double[] lat,double[] lon,double[] alt){
		
		clearTable(false);
		for(int i=0;i<ch.length;i++){
			addRow(i,ch[i],station[i],component[i],disp[i],pu[i],tblindex[i],factor[i],unit[i],fullscale[i],mask[i],lat[i],lon[i],alt[i]);
		}
	}
	/**
	 * テーブルに追加する
	 * @param idx
	 * @param ch
	 * @param station
	 * @param component
	 * @param disp
	 * @param pu
	 * @param tblindex
	 * @param factor
	 * @param unit
	 * @param fullscale
	 * @param mask
	 * @param lat
	 * @param lon
	 * @param alt
	 */
	private void addRow(int idx,int ch,String station,String component,boolean disp,boolean pu,int tblindex,double factor,String unit,double fullscale,boolean mask,double lat,double lon,double alt){
		Object[] data = new Object[TableColumnName.length];
		data[getColumnFromName("Index")] = idx;
		data[getColumnFromName("Channel")] = String.format("%04X",ch);
		data[getColumnFromName("IndexSub")] = new String("");
		data[getColumnFromName("Station")] = new String(station);
		data[getColumnFromName("Component")] = new String(component);
		data[getColumnFromName("Display")] = disp;
		data[getColumnFromName("PhysicalQuantity")] = pu;
		data[getColumnFromName("IndexSub")] = tblindex;
		data[getColumnFromName("Factor")] = factor;
		data[getColumnFromName("Unit")] = unit;
		data[getColumnFromName("FullScale")] = fullscale;
		data[getColumnFromName("Mask")] = mask;
		data[getColumnFromName("Latitude")] = lat;
		data[getColumnFromName("Longitude")] = lon;
		data[getColumnFromName("Altitude")] = alt;
		TableModel.addRow(data);
	}
	/**
	 * Indexの最大値を得る
	 * @return
	 */
	private int getMaxIndex(){
		int max = TableModel.getRowCount();
		int col = getColumnFromName("Index");
		int ret = 0;
		for(int i=0;i<max;i++){
			int idx = (Integer)TableModel.getValueAt(i, col);
			if(idx>ret) ret = idx;
		}
		return ret;
	}
	/**
	 * 未使用のChを得る。
	 * @return
	 */
	private int getUnUsedCh(){
		int max = TableModel.getRowCount();
		int col = getColumnFromName("Channel");
		HashSet<Integer> ts  =new HashSet<Integer>();  
		for(int i=0;i<max;i++){
			Object o = TableModel.getValueAt(i, col);
			if(o instanceof String){
				String s = (String)o;
				int ch = Integer.valueOf(s,16);
				ts.add(ch);
			}
			else if(o instanceof Integer){
				ts.add((Integer)o);
			}
		}
		for( int i=0;i<0xffff;i++){
			if(!ts.contains(i)) return i;
		}
		return -1; // 全部埋まっている
	}
	/**
	 * １つのＣＨデータをセットする。 CHがない場合は新規に末尾に追加する。
	 * @param ch
	 * @param station
	 * @param component
	 * @param disp
	 * @param pu
	 * @param tblindex
	 * @param factor
	 * @param unit
	 * @param fullscale
	 * @param mask
	 * @param lat
	 * @param lon
	 * @param alt
	 */
	private void setRow(int ch,String station,String component,boolean disp,boolean pu,int tblindex,double factor,String unit,double fullscale,boolean mask,double lat,double lon,double alt){
		
		int row = findRow(ch);
		
		if(row == -1){
			int idx = getMaxIndex();
//			int idx = TableModel.getRowCount();
			addRow(idx + 1,ch,station,component,disp,pu,tblindex,factor,unit,fullscale,mask,lat,lon,alt);
			return;
		}
		TableModel.setValueAt(new String(""), row, getColumnFromName("IndexSub"));
		TableModel.setValueAt(new String(station), row, getColumnFromName("Station"));
		TableModel.setValueAt(new String(component), row, getColumnFromName("Component"));
		TableModel.setValueAt(disp, row, getColumnFromName("Display"));
		TableModel.setValueAt(pu, row, getColumnFromName("PhysicalQuantity"));
		TableModel.setValueAt(tblindex, row, getColumnFromName("IndexSub"));
		TableModel.setValueAt(factor, row, getColumnFromName("Factor"));
		TableModel.setValueAt(unit, row, getColumnFromName("Unit"));
		TableModel.setValueAt(fullscale, row, getColumnFromName("FullScale"));
		TableModel.setValueAt(mask, row, getColumnFromName("Mask"));
		TableModel.setValueAt(lat, row, getColumnFromName("Latitude"));
		TableModel.setValueAt(lon, row, getColumnFromName("Longitude"));
		TableModel.setValueAt(alt, row, getColumnFromName("Altitude"));
	}
	
	/**
	 * LinkedList<ChannelDisplayPropertyData>から追加する。
	 * @param d
	 */
	private void setRow(LinkedList<ChannelDisplayPropertyData> d){
		Iterator<ChannelDisplayPropertyData> ite = d.iterator();
		while(ite.hasNext()){
			ChannelDisplayPropertyData c = ite.next();
			setRow(c.ch,c.station,c.component,c.disp,c.pu,c.tblindex,c.factor,c.unit,c.fullscale,c.mask,c.lat,c.lon,c.alt);
		}

	}
	/**
	 * chのＲＯＷを見つける
	 * @param ch
	 * @return
	 */
	private int findRow(int ch){
		int col = getColumnFromName("Channel");
		for(int i=0;i<TableModel.getRowCount();i++){
			String s = (String)TableModel.getValueAt(i, col); 
			int c = Integer.valueOf(s,16); 
			if(c == ch) return i;
		}
		return -1;
	}
	/**
	 * 名前からcolumn番号を得る
	 * @param name
	 * @return
	 */
	private int getColumnFromName(String name){
		int i;
		for(i=0;i<TableColumnName.length;i++){
			if(TableColumnName[i].compareToIgnoreCase(name)==0) break;
		}
		return i;
	}
	/**
	 * channel すべてのＣＨを取得する
	 * @return
	 */
	public int[] getChannel(){
		int col = getColumnFromName("Channel");
		int count = getJTableDisplayProperty().getRowCount();
		int[] ret = new int[count];
		for(int i=0;i<count;i++){
			String str = TableModel.getValueAt(i, col).toString();
			ret[i] = Integer.parseInt(str,16);
		}
		return ret;
	}
	/**
	 * channel すべての選択されているＣＨを取得する
	 * @return
	 */
	public int[] getSelectedChannel(){
		int row[] = jTableDisplayProperty.getSelectedRows();
		for(int i=0;i<row.length;i++){
			row[i] = jTableDisplayProperty.convertRowIndexToModel(row[i]);
		}
		return row;
	}
	
	public boolean isDisplay(int index){
		return TableModel.getValueAt(index,getColumnFromName("Display") ).equals(true);
	}
	public boolean isPU(int index){
		return TableModel.getValueAt(index,getColumnFromName("PhysicalQuantity") ).equals(true);
	}
	public String getStation(int index){
		return TableModel.getValueAt(index,getColumnFromName("Station") ).toString();
	}
	public String getChComponent(int index){
		return TableModel.getValueAt(index,getColumnFromName("Component") ).toString();
	}
	public int getChannelTableIndex(int index){
		return Integer.valueOf(TableModel.getValueAt(index,getColumnFromName("IndexSub") ).toString());
	}
	// "Factor","Unit","FullScale"
	public double getFactor(int index){
		return Double.valueOf(TableModel.getValueAt(index,getColumnFromName("Factor") ).toString());
		//return (Double)TableModel.getValueAt(index,getColumnFromName("Factor") );
	}
	public String getUnit(int index){
		return TableModel.getValueAt(index,getColumnFromName("Unit") ).toString();
		//return (String)TableModel.getValueAt(index,getColumnFromName("Unit") );
	}
	public long getFullScale(int index){
		Double d = Double.valueOf(TableModel.getValueAt(index,getColumnFromName("FullScale") ).toString());
		return d.longValue();
		//return (Long)TableModel.getValueAt(index,getColumnFromName("FullScale") );
	}
	public boolean getMask(int index){
		return TableModel.getValueAt(index,getColumnFromName("Mask") ).equals(true);
	}
	public double getLatitude(int index){
		return Double.valueOf(TableModel.getValueAt(index,getColumnFromName("Latitude") ).toString());
	}
	public double getLongitude(int index){
		return Double.valueOf(TableModel.getValueAt(index,getColumnFromName("Longitude") ).toString());
	}
	public double getAltitude(int index){
		return Double.valueOf(TableModel.getValueAt(index,getColumnFromName("Altitude") ).toString());
	}
	//------------------------------------------------------
	// 表示ｃｈリストを返す
	public ArrayList<Integer> getChannelSequence(){
		ArrayList<Integer> ret = new ArrayList<Integer>();
		int col = getColumnFromName("Channel");
		for(int vrow = 0;vrow<TableModel.getRowCount();vrow++){
			
			int ch = Integer.valueOf(jTableDisplayProperty.getValueAt(vrow,col).toString(),16);
			ret.add(ch);
		}
		return ret;
	}
	/**
	 * This method initializes jButtonOK	
	 * 	
	 * @return javax.swing.JButton	
	 */
	private JButton getJButtonOK() {
		if (jButtonOK == null) {
			jButtonOK = new JButton();
			jButtonOK.setToolTipText("Save to Channel.ini");
			jButtonOK.setText("Save");
			jButtonOK.addActionListener(new java.awt.event.ActionListener() {
				public void actionPerformed(java.awt.event.ActionEvent e) {
					
					//jTableDisplayProperty.editingStopped(null);// 編集中のデータを取り込む
					Parent.actionPerformed(e);
				}
			});
		}
		return jButtonOK;
	}

	/**
	 * This method initializes jButtonCANCEL	
	 * 	
	 * @return javax.swing.JButton	
	 */
	private JButton getJButtonCANCEL() {
		if (jButtonCANCEL == null) {
			jButtonCANCEL = new JButton();
			jButtonCANCEL.setToolTipText("Abort all chenges");
			jButtonCANCEL.setText("CANCEL");
			jButtonCANCEL.addActionListener(new java.awt.event.ActionListener() {
				public void actionPerformed(java.awt.event.ActionEvent e) {
					Parent.actionPerformed(e);
				}
			});
		}
		return jButtonCANCEL;
	}

	/**
	 * This method initializes jContentPane	
	 * 	
	 * @return javax.swing.JPanel	
	 */
	private JPanel getJContentPane() {
		if (jContentPane == null) {
			jContentPane = new JPanel();
			jContentPane.setLayout(new BorderLayout());
			jContentPane.add(getJPanelSouth(), BorderLayout.SOUTH);  // Generated
			jContentPane.add(getJScrollPaneTable(), BorderLayout.CENTER);  // Generated
			jContentPane.add(getMenuBar(), BorderLayout.NORTH);
		}
		return jContentPane;
	}

	/**
	 * This method initializes jScrollPaneTable	
	 * 	
	 * @return javax.swing.JScrollPane	
	 */
	private JScrollPane getJScrollPaneTable() {
		if (jScrollPaneTable == null) {
			jScrollPaneTable = new JScrollPane();
			jScrollPaneTable.setViewportView(getJTableDisplayProperty());
		}
		return jScrollPaneTable;
	}

	/**
	 * This method initializes jTableDisplayProperty	
	 * 	
	 * @return javax.swing.JTable	
	 */
	private JTable getJTableDisplayProperty() {
		if (jTableDisplayProperty == null) {
			TableModel = new CustomTableModel(TableData,TableColumnName); 	//@ 
			//TableModel = new CustomTableModel(); 	// @ 
			jTableDisplayProperty = new JTable(TableModel); // @
			jTableDisplayProperty.addFocusListener(new FocusAdapter() {
				// フォーカスを失ったときに編集を終了する。
				@Override
				public void focusLost(FocusEvent arg0) {
					if(jTableDisplayProperty.isEditing()){
						jTableDisplayProperty.getCellEditor().stopCellEditing();
					}
				}
			});
			jTableDisplayProperty.setBorder(new EtchedBorder(EtchedBorder.LOWERED, null, null));
			jTableDisplayProperty.setAutoResizeMode(JTable.AUTO_RESIZE_SUBSEQUENT_COLUMNS);
			//jTableDisplayProperty.setPreferredSize(new Dimension(100, 100));
		//	jTableDisplayProperty.setDefaultEditor(Object.class, null);
			jTableDisplayProperty.setColumnSelectionAllowed(true);
			jTableDisplayProperty.setRowSelectionAllowed(true);
			jTableDisplayProperty.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
			jTableDisplayProperty.setDefaultRenderer(Double.class, new DoubleRenderer());
			jTableDisplayProperty.setAutoCreateRowSorter(true);
			jTableDisplayProperty.getColumnModel().getColumn(getColumnFromName("Index")).setMinWidth(10);
			jTableDisplayProperty.getColumnModel().getColumn(getColumnFromName("FullScale")).setMinWidth(70);
			jTableDisplayProperty.getColumnModel().getColumn(getColumnFromName("Factor")).setMinWidth(70);
			
			jTableDisplayProperty.addMouseListener(this);

			jTableDisplayProperty.addMouseListener(new java.awt.event.MouseAdapter() {
				public void mouseClicked(java.awt.event.MouseEvent e) {
					if(e.getClickCount()==2) {
					}
				}
			});
			
			
			initCopyPeast();
		}
		return jTableDisplayProperty;
	}
	
	private 		JMenuItem jmenuitemCut;
	private 		JMenuItem jmenuitemCopy; 
	private 		JMenuItem jmenuitemPaset;

	private void initCopyPeast(){
		//* -------------------------------------------------------------
		// キーイベント用アクション生成
		TableEditActionListener actionCut = new TableEditActionListener(jTableDisplayProperty, "Cut");
		TableEditActionListener actionCopy = new TableEditActionListener(jTableDisplayProperty, "Copy");
		TableEditActionListener actionPaste = new TableEditActionListener(jTableDisplayProperty, "Paste");

		// キーの登録
		jTableDisplayProperty.getInputMap().put(CUT, "Cut");				// 切り取り
		jTableDisplayProperty.getActionMap().put("Cut", actionCut);
		jTableDisplayProperty.getInputMap().put(COPY, "Copy");				// コピー
		jTableDisplayProperty.getActionMap().put("Copy", actionCopy);
		jTableDisplayProperty.getInputMap().put(PASTE, "Paste");			// 貼り付け
		jTableDisplayProperty.getActionMap().put("Paste", actionPaste);

		// 右クリック用のメニューを定義
		jmenuitemCut = new JMenuItem("Cut    Ctrl+X");			// 切り取り
		jmenuitemCopy = new JMenuItem("Copy   Ctrl+C");			// コピー
		jmenuitemPaset = new JMenuItem("Paste  Ctrl+V");			// 貼り付け

		// 右クリック用アクションリスナー生成
		TableEditActionListener listener
			= new TableEditActionListener(jTableDisplayProperty, jmenuitemCut, jmenuitemCopy, jmenuitemPaset);

		// 各メニュー選択時の処理
		jmenuitemCut.addActionListener(listener);
		jmenuitemCopy.addActionListener(listener);
		jmenuitemPaset.addActionListener(listener);
		// TODO: ブール値にペーストすると例外（テキストからブールに変換できない）が発生する問題をなんとかすること。
		
//		// マウスイベント用リスナー追加
//		jTableDisplayProperty.addMouseListener(new SampleMouseListener(
//				jTableDisplayProperty, jpopup));
//		// ポップアップをフレームに設定
//		this.add(jpopup);

		//* -------------------------------------------------------------
	
	}
	private void addPopupMenuCopyPeast(JPopupMenu jpopup){
		// 右クリック時に表示するポップアップを定義
		// JPopupMenu jpopup = new JPopupMenu();
		jpopup.add(jmenuitemCut);				// Cut    Ctrl+X
		jpopup.add(jmenuitemCopy);				// Copy   Ctrl+C
		jpopup.add(jmenuitemPaset);				// Paste  Ctrl+V
		return;
		
	}
	@Override
	public void actionPerformed(ActionEvent e) {
		
	}
	@Override
	public void itemStateChanged(ItemEvent e) {
		
	}
	
	private DialogFactor dlgFactor = null;
	private int FactorRow = -1;
	private int[] FactorRowSelected = null;
	private JMenuBar menuBar;
	private JMenu mnFile;
	private JMenuItem mntmOpen;
	private JMenuItem mntmSaveAs;
	
	public void mouseClicked(MouseEvent e) {
		MouseClickPoint = getLocationOnScreen();
		MouseClickPoint.x += e.getX();
		MouseClickPoint.y += e.getY();
		// 右クリックのコンテキストメニューを動的に生成
		if (SwingUtilities.isRightMouseButton(e)) {
			int col = jTableDisplayProperty.columnAtPoint(new Point(e.getX(),e.getY()));
			col = jTableDisplayProperty.convertColumnIndexToModel(col);
			if(col == getColumnFromName("Display")){
				PopupMenu= new JPopupMenu();
				addPopupMenuItem(PopupMenu,"Set   selected items", new ActionListener(){ 
					public void actionPerformed(ActionEvent e) {
						setSelectedItemSet(true);
					}
			    });
				addPopupMenuItem(PopupMenu,"Reset selected items", new ActionListener(){ 
					public void actionPerformed(ActionEvent e) {
						setSelectedItemSet(false);
					}
			    });
				addPopupMenuItem(PopupMenu,"Reset   all Display", new ActionListener(){ 
					public void actionPerformed(ActionEvent e) {
						setAllItemSet(false,"Display");
					}
			    });
				addPopupMenuItem(PopupMenu,"Special pattern...", new ActionListener(){ 
					public void actionPerformed(ActionEvent ae) {
						doSpecialPatternDialog("Display");
					}
			    });
				
				PopupMenu.addSeparator();
				addPopupMenuCopyPeast(PopupMenu);
				PopupMenu.show(e.getComponent(), e.getX(), e.getY());
			}
			if(col == getColumnFromName("Index") || col == getColumnFromName("IndexSub")){
				PopupMenu= new JPopupMenu();
				if(isAnythingSelected()){
					addPopupMenuItem(PopupMenu,"Delete row", new ActionListener(){ 
						public void actionPerformed(ActionEvent e) {
							deleteRow();
						}
				    });
					PopupMenu.addSeparator();
				}
				addPopupMenuCopyPeast(PopupMenu);
				PopupMenu.show(e.getComponent(), e.getX(), e.getY());
			}
			else if(col == getColumnFromName("PhysicalQuantity")){
				PopupMenu= new JPopupMenu();
				addPopupMenuItem(PopupMenu,"Set   selected items", new ActionListener(){ 
					public void actionPerformed(ActionEvent e) {
						setSelectedItemSet(true);
					}
			    });
				addPopupMenuItem(PopupMenu,"Reset selected items", new ActionListener(){ 
					public void actionPerformed(ActionEvent e) {
						setSelectedItemSet(false);
					}
			    });
				addPopupMenuItem(PopupMenu,"Set   all PhysicalQuantity", new ActionListener(){ 
					public void actionPerformed(ActionEvent e) {
						setAllItemSet(true,"PhysicalQuantity");
					}
			    });
				addPopupMenuItem(PopupMenu,"Reset all PhysicalQuantity", new ActionListener(){ 
					public void actionPerformed(ActionEvent e) {
						setAllItemSet(false,"PhysicalQuantity");
					}
			    });
				addPopupMenuItem(PopupMenu,"Special pattern...", new ActionListener(){ 
					public void actionPerformed(ActionEvent ae) {
						doSpecialPatternDialog("PhysicalQuantity");
					}
			    });
				PopupMenu.addSeparator();
				addPopupMenuCopyPeast(PopupMenu);
				PopupMenu.show(e.getComponent(), e.getX(), e.getY());
				
			}
			else if(col == getColumnFromName("Mask")){
				PopupMenu= new JPopupMenu();
				addPopupMenuItem(PopupMenu,"Set   selected items", new ActionListener(){ 
					public void actionPerformed(ActionEvent e) {
						setSelectedItemSet(true);
					}
			    });
				addPopupMenuItem(PopupMenu,"Reset selected items", new ActionListener(){ 
					public void actionPerformed(ActionEvent e) {
						setSelectedItemSet(false);
					}
			    });
				addPopupMenuItem(PopupMenu,"Set   all Mask", new ActionListener(){ 
					public void actionPerformed(ActionEvent e) {
						setAllItemSet(true,"Mask");
					}
			    });
				addPopupMenuItem(PopupMenu,"Reset all Mask", new ActionListener(){ 
					public void actionPerformed(ActionEvent e) {
						setAllItemSet(false,"Mask");
					}
			    });
				addPopupMenuItem(PopupMenu,"Special pattern...", new ActionListener(){ 
					public void actionPerformed(ActionEvent ae) {
						doSpecialPatternDialog("Mask");
					}
			    });
				PopupMenu.addSeparator();
				addPopupMenuCopyPeast(PopupMenu);
				PopupMenu.show(e.getComponent(), e.getX(), e.getY());
				
			}
			else if(col == getColumnFromName("Channel")||
					col == getColumnFromName("Station")||
					col == getColumnFromName("Component")||
					col == getColumnFromName("Longitude")||
					col == getColumnFromName("Latitude") ||
					col == getColumnFromName("Altitude") ){
				if(isValidLocation()){
					PopupMenu= new JPopupMenu();
					
					addPopupMenuItem(PopupMenu,"Google Map", new ActionListener(){ 
						public void actionPerformed(ActionEvent ae) {
							showMapsSelectedLocation();
						}
					},new ImageIcon(getClass().getClassLoader().getResource("images/map.png")));
					
					JMenuItem pi2 =addPopupMenuItem(PopupMenu,"Google Earth", new ActionListener(){ 
						public void actionPerformed(ActionEvent ae) {
							showEarthSelectedLocation();
						}
					},new ImageIcon(getClass().getClassLoader().getResource("images/earth.png")));
					PopupMenu.addSeparator();
					addPopupMenuCopyPeast(PopupMenu);
					PopupMenu.show(e.getComponent(), e.getX(), e.getY());
				}
			}
			else if((col == getColumnFromName("Factor"))||(col == getColumnFromName("FullScale"))||(col == getColumnFromName("Unit"))){
				PopupMenu= new JPopupMenu();
				addPopupMenuItem(PopupMenu,"Set up physical conversion ", new ActionListener(){ 
					public void actionPerformed(ActionEvent e) {
						dlgFactor.setVisible(true);
						if(dlgFactor.getReturn()){
							String unit = new String(dlgFactor.getUnitString());
							double factor = dlgFactor.getFactor();
							long fullscale = dlgFactor.getFullScale();
							if(FactorRow>=0){
								for(int i=0;i<FactorRowSelected.length;i++){
									int r = jTableDisplayProperty.convertRowIndexToModel(FactorRowSelected[i]);
									TableModel.setValueAt(factor,r,getColumnFromName("Factor") );
									TableModel.setValueAt(fullscale,r,getColumnFromName("FullScale") );
									TableModel.setValueAt(unit,r,getColumnFromName("Unit") );
								}
							}
						}
					}
			    });
				int row = jTableDisplayProperty.rowAtPoint(new Point(e.getX(),e.getY()));
				FactorRow = jTableDisplayProperty.convertRowIndexToModel(row);
				FactorRowSelected= jTableDisplayProperty.getSelectedRows();
				
				PopupMenu.addSeparator();
				addPopupMenuCopyPeast(PopupMenu);
				PopupMenu.show(e.getComponent(), e.getX(), e.getY());
			}
		}
	}
	private boolean isAnythingSelected(){
		if(jTableDisplayProperty.getSelectedRow()>=0) return true;
		return false;
	}
	/**
	 * 行を削除する。
	 */
	protected void deleteRow() {
		while(true){
			int row[] = jTableDisplayProperty.getSelectedRows();
			if(row.length<1){
				break;
			}
			int r =  jTableDisplayProperty.convertRowIndexToModel(row[0]);
			TableModel.removeRow(r);
		}
		
	}
	// 指定カラムからdoubleの値を読みだす
	private double getDoubleValue(int low,String column){
		double ret = Double.NaN;
		String str = jTableDisplayProperty.getValueAt(low,getColumnFromName(column)).toString();
		try{
			ret = Double.parseDouble(str);
		} catch (NumberFormatException e){
			e.printStackTrace();
		}
		return ret;
	}
	
	// 選択しているrowにlongitude,latitudeがセットされているかどうかを調べる
	// 
	private boolean isValidLocation(){
		boolean ret = false;
		int row[] = jTableDisplayProperty.getSelectedRows();
		for(int i=0;i<row.length;i++){
			double lon = getDoubleValue(row[i],"Longitude");
			double lat = getDoubleValue(row[i],"Latitude");
			double alt = getDoubleValue(row[i],"Altitude");
			if(lon == Double.NaN || lat == Double.NaN || alt == Double.NaN){
				return false;
			}
			else ret = true;
		}
		return ret;
	}
	
	// 経度、緯度でgoogleマップを開く
	private void showMapsSelectedLocation(){
		int row[] = jTableDisplayProperty.getSelectedRows();
		if(row.length>4){
			if(JOptionPane.YES_OPTION != JOptionPane.showConfirmDialog(null, String.format("Open ( %d ) URL. It can take long time. OK?",row.length),"Opening URL",JOptionPane.YES_NO_OPTION)){
				return;
			}
		}
		for(int i=0;i<row.length;i++){
			double lon = getDoubleValue(row[i],"Longitude");
			double lat = getDoubleValue(row[i],"Latitude");
			double alt = getDoubleValue(row[i],"Altitude");
			String title = jTableDisplayProperty.getValueAt(row[i],getColumnFromName("Channel")).toString();
			String station = jTableDisplayProperty.getValueAt(row[i],getColumnFromName("Station")).toString();
			String component = jTableDisplayProperty.getValueAt(row[i],getColumnFromName("Component")).toString();
			if(lon == 0.0 && lat == 0.0){
				if(JOptionPane.CANCEL_OPTION ==JOptionPane.showConfirmDialog(null, "Invalid Logitude or Latitude " + title,"Error",JOptionPane.OK_CANCEL_OPTION)){
					break;
				}
				else {
					continue;
				}
			}
			if(station != null) title += (" " + station);
			if(component != null) title += (" " + component);
			if(!MapUtil.showMap(lat, lon, title)){
				break;
			}
		}
	}

	
	// 経度、緯度でgoogle Eartchを開く
	private void showEarthSelectedLocation(){
		int row[] = jTableDisplayProperty.getSelectedRows();
		
		ArrayList<Double> lon = new ArrayList<Double>();
		ArrayList<Double> lat = new ArrayList<Double>();
		ArrayList<Double> alt = new ArrayList<Double>();
		ArrayList<String> tit = new ArrayList<String>();
		for(int i=0;i<row.length;i++){
			double lon2 = getDoubleValue(row[i],"Longitude");
			double lat2 = getDoubleValue(row[i],"Latitude");
			double alt2 = getDoubleValue(row[i],"Altitude");
			String title = jTableDisplayProperty.getValueAt(row[i],getColumnFromName("Channel")).toString();
			String station = jTableDisplayProperty.getValueAt(row[i],getColumnFromName("Station")).toString();
			String component = jTableDisplayProperty.getValueAt(row[i],getColumnFromName("Component")).toString();
			if(lon2 == 0.0 && lat2 == 0.0){
				if(JOptionPane.CANCEL_OPTION ==JOptionPane.showConfirmDialog(null, "Invalid Logitude or Latitude " + title,"Error",JOptionPane.OK_CANCEL_OPTION)){
					break;
				}
				else {
					continue;
				}
			}
			if(station != null) title += (" " + station);
			if(component != null) title += (" " + component);
			tit.add(title);
			lon.add(lon2);
			lat.add(lat2);
			alt.add(alt2);
		}
		MapUtil.showEarth(lat, lon,alt, tit);
	}

	private void doSpecialPatternDialog(String column){
		Component c=this;
		while(c!=null){
			c=c.getParent();
			if(c instanceof JFrame) break;
		}
		DialogSetResetPattern dlg = new DialogSetResetPattern((JFrame)c);//@
		//dlg.setLocation(MouseClickPoint.x,MouseClickPoint.y);//@	
		dlg.setLocation(this.getX(),this.getY());//@	
		dlg.setTitle(dlg.getTitle()+" for " + column);//@
		dlg.setVisible(true);	//@
		if(dlg.OK){
			boolean equal = dlg.Equal;
			boolean set = dlg.Set;
			int num = dlg.Number;
			setMaskSpecialPattern(column,num,equal,set);
		}
		
	}
	
	@Override
	public void mouseEntered(MouseEvent e) {
		
	}
	@Override
	public void mouseExited(MouseEvent e) {
		
	}
	@Override
	public void mousePressed(MouseEvent e) {

		
	}
	@Override
	public void mouseReleased(MouseEvent e) {
		
	}
	/**
	 * This method initializes jPanelSouth	
	 * 	
	 * @return javax.swing.JPanel	
	 */
	private JPanel getJPanelSouth() {
		if (jPanelSouth == null) {
			jPanelSouth = new JPanel();
			jPanelSouth.setPreferredSize(new Dimension(100, 26));
			jPanelSouth.setLayout(new BorderLayout(0, 0));
			
			JPanel panel_1 = new JPanel();
			panel_1.setPreferredSize(new Dimension(200, 24));
			panel_1.setMinimumSize(new Dimension(100, 20));
			jPanelSouth.add(panel_1, BorderLayout.EAST);
			panel_1.setLayout(new GridLayout(0, 2, 0, 0));
			panel_1.add(getJButtonCANCEL());
			panel_1.add(getJButtonOK());
		}
		return jPanelSouth;
	}
	// ----------------------------------------------------------------------
	// win channel table を選択するダイアログ
	private File chooseChannelTableFile(){
		JFileChooser filechooser = new JFileChooser(ChannelTableFileFolder);//@
		filechooser.setFileSelectionMode( JFileChooser.FILES_ONLY);
		filechooser.setDialogTitle("Open win channel table file");
		int selected = filechooser.showOpenDialog(this);
		File file = null;
		if ( selected == JFileChooser.APPROVE_OPTION ) {
			file = filechooser.getSelectedFile ();
		}
		return file;
		
	}
	// ファイルからwin channel table を読み出す
//  #            [0]Index
//	#            [1]２バイトのチャネル番号（16進数）
//	#            [2]収録フラグ
//	#            [3]回線遅延時間(ms)
//	#            [4]１０文字以内の観測点コード
//	#            [5]６文字以内の成分コード
//	#            [6]モニター波形の振幅縮率を示す指数（２の累乗数）
//	#            [7]A/D変換の量子化ビット数
//	#            [8]センサーの感度（V/入力振幅単位、入力振幅単位は[9]で示す）、実数でもよい
//	#            [9][8]における入力振幅単位、MKS系で、変位は"m"、速度は"m/s"、加速度は"m/s/s"と書くこと
//	#            [10]地震計の固有周期(s)
//	#            [11]地震計のダンピング定数
//	#            [12]センサー出力からA/D変換までの電圧増幅率(dB)
//	#            [13]A/D変換の１量子化ステップ幅(V)
//	#            [14]観測点の緯度(°)、北緯を正とする
//	#            [15]観測点の経度(°)、東経を正とする
//	#            [16]観測点の海抜高度(m)
//	#            [17]P波の観測点補正(s)、これを観測値に足して震源計算する
//	#            [18]S波の観測点補正(s)、同上 
	public void readChannelTable(File file){
		try {
			ChannelTableFilePath = file.getAbsolutePath();
			ChannelTableFileFolder = file.getParent();
		    FileReader in = new FileReader(file);
            BufferedReader br = new BufferedReader(in);
            String line;
            int count=0;
            while ((line = br.readLine()) != null) {
                String[] aaa = line.split("[;#]");
                line = aaa[0];
            	line = line.trim();
                if(line.isEmpty()) continue;
                if(line.charAt(0) == '#') continue;
                String[] tok = line.split("[ \t]+");
                if(tok.length < (1) ) continue;
                String[] num = new String[tok.length+1];
                num[0] = String.valueOf(count++);
                for(int i=1;i<num.length;i++){
                	num[i] = tok[i-1];
                }
                ChannelTable.add(num);
            }
            br.close();
            in.close();
            
            readChannelTable();
			
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
	}
	// channel table を表にセットする
	private void readChannelTable(){
		if(Mode==1){//  テーブルに表示されていないｃｈも読み出す。
			Iterator<String[]> ite = ChannelTable.iterator();
			while(ite.hasNext()){
				String[] str = ite.next();
				int ch = Integer.valueOf(str[1],16);
				int row = findTableModelIndex(ch);
				if(row<0){
					Object[] data = new Object[TableColumnName.length];
					data[getColumnFromName("Index")] = TableModel.getRowCount();
					data[getColumnFromName("Channel")] = String.format("%04x",ch);
					
					data[getColumnFromName("IndexSub")] = new String("");
					data[getColumnFromName("Station")] = new String("");
					data[getColumnFromName("Component")] = new String("");
					data[getColumnFromName("Display")] = false;
					data[getColumnFromName("PhysicalQuantity")] = false;
					data[getColumnFromName("IndexSub")] = 0;
					data[getColumnFromName("Factor")] = 0.0;
					data[getColumnFromName("Unit")] = new String("");;
					data[getColumnFromName("FullScale")] = 100L;
					data[getColumnFromName("Mask")] = false;
					data[getColumnFromName("Latitude")] = 0.0;
					data[getColumnFromName("Longitude")] = 0.0;
					data[getColumnFromName("Altitude")] = 0.0;
					
					TableModel.addRow(data);
				}
			}
		}
		int station = getColumnFromName("Station");
		int component = getColumnFromName("Component");
		int tblindex =  getColumnFromName("IndexSub");
		int factorindex = getColumnFromName("Factor");
		int unitindex = getColumnFromName("Unit");
		int fsindex = getColumnFromName("FullScale");
		int latindex = getColumnFromName("Latitude");
		int lonindex = getColumnFromName("Longitude");
		int altindex = getColumnFromName("Altitude");
		// テーブルに表示されているｃｈを選んでChannelTableから読み出す
		int count=0;
		for(int row=0;row<TableModel.getRowCount();row++){
			//int ch = Integer.valueOf(TableModel.getValueAt(row,1).toString(),16);
			int iii = getColumnFromName("Channel");
			int ch = Integer.valueOf(TableModel.getValueAt(row,iii).toString(),16);
			
			
			int idx = findChannelIndex(ch);
			if(idx<0){
				continue;
			}
			count++;
			Object[] obj = ChannelTable.get(idx);// channel tableを探して
			
			int tblidx = Integer.valueOf(obj[0].toString());// チャネル表での順番
			TableModel.setValueAt(tblidx,row,tblindex);
			// 18項目以下でも取り込む
			if(obj.length>4){
				String code = obj[4].toString();			// 観測点コード
				TableModel.setValueAt(code,row,station);
			}
			if(obj.length>5){
				String comp = obj[5].toString();			// 成分
				TableModel.setValueAt(comp,row,component);
			}
			if(obj.length>7){
				int bitlength = Integer.valueOf(obj[7].toString());	// フルスケール
				long fullscale = (long)(Math.pow(2.0, bitlength));
				TableModel.setValueAt(fullscale,row,fsindex);
			}
			if(obj.length>9){
				String unit = obj[9].toString();		// 単位をあらわす文字列
				TableModel.setValueAt(unit,row,unitindex);
			}
			if(obj.length>13){
				double sens = Double.valueOf(obj[8].toString());// センサーの感度 V/単位
				double anaamp = Double.valueOf(obj[12].toString());// アンプの倍率dB
				anaamp = Math.pow(10.0, anaamp/20.0);
				double adcstep = Double.valueOf(obj[13].toString()); // ADC ステップ 	V/digit
				Double factor = new Double(adcstep * anaamp / sens);  // 単位/digit 物理量換算係数
				TableModel.setValueAt(factor,row,factorindex);
			}
			if(obj.length>14){
				double data = Double.valueOf(obj[14].toString());// latitude
				TableModel.setValueAt(data,row,latindex);
			}
			if(obj.length>15){
				double data = Double.valueOf(obj[15].toString());// longitude
				TableModel.setValueAt(data,row,lonindex);
			}
			if(obj.length>16){
				double data = Double.valueOf(obj[16].toString());// altitude
				TableModel.setValueAt(data,row,altindex);
			}
			
		}
		JOptionPane.showConfirmDialog(this, String.format("%d line(s) read", count),"Import win channel table",JOptionPane.CLOSED_OPTION, JOptionPane.INFORMATION_MESSAGE);
		
	}
	private int findTableModelIndex(int ch){
		int ret = -1;
		int channel = getColumnFromName("Channel");
		for(int row=0;row<TableModel.getRowCount();row++){
			int tch = Integer.valueOf(TableModel.getValueAt(row,channel).toString(),16);
			if(ch == tch) return row;
		}
		return ret;
	}
	/**
	 *  ChannelTableから指定ｃｈのインデックスを見つける
	 * @param ch
	 * @return
	 */
	private int findChannelIndex(int ch){
		int ret = 0;
		Iterator<String[]> ite = ChannelTable.iterator();
		int max = ChannelTable.size();
		while(ite.hasNext()){
			String[] s= ite.next();
			if(Integer.valueOf(s[1],16) == ch){
				break;
			}
			ret++;
		}
		if(ret>=max) ret = -1;
		return ret;
	}
	/**
	 * This method initializes jTextFieldCalculator	
	 * 	
	 * @return javax.swing.JTextField	
	 */
	private JTextField getJTextFieldCalculator() {
		if (jTextFieldCalculator == null) {
			jTextFieldCalculator = new NumericTextField();
			jTextFieldCalculator.setPreferredSize(new Dimension(100,25));
		}
		return jTextFieldCalculator;
	}
	private JMenuBar getMenuBar() {
		if (menuBar == null) {
			menuBar = new JMenuBar();
			menuBar.add(getMnFile());
			menuBar.add(getMnData());
			menuBar.add(getPanel());
		}
		return menuBar;
	}
	private JMenu getMnFile() {
		if (mnFile == null) {
			mnFile = new JMenu("File");
			mnFile.addMenuListener(new MenuListener() {
				public void menuCanceled(MenuEvent arg0) {
				}
				public void menuDeselected(MenuEvent arg0) {
				}
				public void menuSelected(MenuEvent arg0) {
					onFileMenuSelected();
				}
			});
			mnFile.setIcon(new ImageIcon(DialogChannelDisplayProperty.class.getResource("/images/folder_classic.png")));
			mnFile.setMargin(new Insets(0, 10, 0, 10));
			mnFile.setMnemonic('F');
			mnFile.add(getMntmOpen());
			mnFile.add(getMntmImportWinChannel());
			mnFile.add(getMntmMenuItemClear());
			mnFile.add(getMntmSaveAs());
			mnFile.add(getMntmSaveAsSelected());
		}
		return mnFile;
	}
	/**
	 * 
	 */
	protected void onFileMenuSelected() {
		// TODO Auto-generated method stub
		boolean en = false;
		if(Mode == 1) {
			en = true;
		}
		getMntmOpen().setEnabled(en);
		getMntmImportWinChannel().setEnabled(en);
		getMntmMenuItemClear().setEnabled(en);
	}
	private JMenuItem getMntmOpen() {
		if (mntmOpen == null) {
			mntmOpen = new JMenuItem("Read");
			mntmOpen.setIcon(new ImageIcon(DialogChannelDisplayProperty.class.getResource("/images/folder_classic_up.png")));
			mntmOpen.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					JFileChooser filechooser = new JFileChooser();
					filechooser.setFileSelectionMode( JFileChooser.FILES_ONLY);	      
					FileNameExtensionFilter filter = new FileNameExtensionFilter("channel ini file", "ini");
					filechooser.addChoosableFileFilter(filter);
					filechooser.setDialogTitle("Read file");
					int selected = filechooser.showOpenDialog(null);
					if ( selected == JFileChooser.APPROVE_OPTION ) {
						File tmp = filechooser.getSelectedFile();
						if(tmp.exists()){
							String filename = tmp.getAbsolutePath();
							ChannelDisplayPropertyData d = new ChannelDisplayPropertyData();
							LinkedList<ChannelDisplayPropertyData>  p = d.readFile(filename);
							setRow(p);
							
						}
					}
				}
			});
		}
		return mntmOpen;
	}
	/**
	 * ファイルを選んでライトする。
	 * @param all
	 */
	private void saveAs(boolean all){
		JFileChooser filechooser = new JFileChooser();
		filechooser.setFileSelectionMode( JFileChooser.FILES_ONLY);	      
		FileNameExtensionFilter filter = new FileNameExtensionFilter("channel ini file", "ini");
		filechooser.addChoosableFileFilter(filter);
		filechooser.setDialogTitle("Save as");
		int selected = filechooser.showSaveDialog(null);
		if ( selected == JFileChooser.APPROVE_OPTION ) {
			File tmp = filechooser.getSelectedFile();
			if(tmp.exists()){
				if(JOptionPane.NO_OPTION ==  JOptionPane.showConfirmDialog(null, "Over write ?","Confirmation",JOptionPane.YES_NO_OPTION)){
					return;
				}
			}
			String filename = tmp.getAbsolutePath();
			ChannelDisplayPropertyData d = new ChannelDisplayPropertyData();
			d.writeFile(filename,getData(all));
		}
		
	}
	/**
	 * ファイルに保存する。
	 * @return
	 */
	private JMenuItem getMntmSaveAs() {
		if (mntmSaveAs == null) {
			mntmSaveAs = new JMenuItem("Save as (all)");
			mntmSaveAs.setIcon(new ImageIcon(DialogChannelDisplayProperty.class.getResource("/images/folder_classic_down.png")));
			mntmSaveAs.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					saveAs(true);
				}
			});
		}
		return mntmSaveAs;
	}

	/**
	 * テーブルのデータをすべて得る
	 * @return
	 */
	private LinkedList<ChannelDisplayPropertyData> getData(boolean all){
		LinkedList<ChannelDisplayPropertyData> ret = new LinkedList<ChannelDisplayPropertyData>();
		int[] c = null;
		if(all) c = getChannel();
		else    c = getSelectedChannel();
		for(int i=0;i<c.length;i++){
			ChannelDisplayPropertyData d = new ChannelDisplayPropertyData();
			d.ch = c[i];
			d.disp = isDisplay(i);
			d.pu = isPU(i);
			d.station = getStation(i);
			d.component = getChComponent(i);
			d.tblindex = i;
			d.factor = getFactor(i);;
			d.unit = getUnit(i);
			d.fullscale = getFullScale(i);;
			d.mask = getMask(i);
			d.lat = getLatitude(i);
			d.lon = getLongitude(i);
			d.alt = getAltitude(i);
			ret.add(d);
		}
		return ret;
	}
	/**
	 * 
	 * データをまとめるクラス
	 * @author ikechan
	 *
	 */
	private static final String BR = System.getProperty("line.separator");
	private JMenuItem mntmSaveAsSelected;
	private JMenuItem mntmMenuItemClear;
	private JMenu mnData;
	private JMenu mnMenuDisplay;
	private JMenuItem mnDisplaySetAll;
	private JMenuItem mnDisplayResetAll;
	private JMenu mnPhysicalQuantitiy;
	private JMenuItem mnPQSetAll;
	private JMenuItem mnPQResetAll;
	private JMenu mnMask;
	private JMenuItem mnMaskSetAll;
	private JMenuItem mnMaskResetAll;
	private JMenuItem mnSpecialPattern;
	private JMenuItem mntmImportWinChannel;
	private JMenuItem mnInsertNew;
	private JPanel panel;
	
	public class ChannelDisplayPropertyData {
		public Integer ch;
		public Boolean disp;
		public Boolean pu;
		public String station;
		public String component;
		public Integer tblindex;
		public Double factor;
		public String unit;
		public Long fullscale;
		public Boolean mask;
		public Double lat;
		public Double lon;
		public Double alt;
		private String Separator = ",";
		/**
		 * ファイルに書き込む。
		 * @param name
		 * @return
		 */
		public boolean writeFile(String name,LinkedList<ChannelDisplayPropertyData> d){
			try {
				// テーブルデータをすべて読みだして
				FileWriter fw  =new FileWriter(new File(name));
				Iterator<ChannelDisplayPropertyData> ite = d.iterator();
				while(ite.hasNext()){
					ChannelDisplayPropertyData c = ite.next();
					fw.write(c.encodeString()+BR);
				}
				fw.flush();
				fw.close();
			} catch (IOException e1) {
				e1.printStackTrace();
				return false;
			}
			return true;
			
		}
		/**
		 * ファイルから自分を読み出す
		 * @param name
		 * @return
		 */
		public LinkedList<ChannelDisplayPropertyData> readFile(String name){
			LinkedList<ChannelDisplayPropertyData> ret = new LinkedList<ChannelDisplayPropertyData>();
			try {
				// テーブルデータをすべて読みだして
				FileReader in  =new FileReader(new File(name));
				BufferedReader br = new BufferedReader(in);
				String line;
				while((line = br.readLine()) != null){
					ChannelDisplayPropertyData d  = new ChannelDisplayPropertyData();
					d.decodeString(line);
					ret.add(d);
				}
				br.close();
			} catch (IOException e1) {
				e1.printStackTrace();
				return null;
			}
			return ret;
			
		}
		/**
		 * 
		 */
		private String encodeString(){
			return new String(
					ch.toString() + Separator  + 
					disp.toString() + Separator + 
					pu.toString() + Separator + 
					station + Separator + 
					component + Separator + 
					tblindex.toString() + Separator + 
					factor.toString() + Separator + 
					unit + Separator + 
					fullscale.toString() + Separator + 
					mask.toString() + Separator + 
					lat.toString() + Separator + 
					lon.toString() + Separator + 
					alt.toString());
		}
		/**
		 * 
		 * @param s
		 */
		private void decodeString(String s){
			String[] tok = s.split(Separator);
			int len = tok.length;
			if(len>=1){
				ch = Integer.valueOf(tok[0]);
			}
			if(len>=2){
				disp = Boolean.valueOf(tok[1]);
			}
			if(len>=3){
				pu = Boolean.valueOf(tok[2]);
			}
			if(len>=4){
				station = tok[3];
			}
			if(len>=5){
				component = tok[4];
			}
			if(len>=6){
				tblindex = Integer.valueOf(tok[5]);
			}
			if(len>=7){
				factor = Double.valueOf(tok[6]);
			}
			if(len>=8){
				unit = tok[7];
			}
			if(len>=9){
				fullscale = Long.valueOf(tok[8]);
			}
			if(len>=10){
				mask = Boolean.valueOf(tok[9]);
			}
			if(len>=11){
				lat = Double.valueOf(tok[10]);
			}
			if(len>=12){
				lon = Double.valueOf(tok[11]);
			}
			if(len>=13){
				alt = Double.valueOf(tok[12]);
			}
		}
	}
	/**
	 * Save as （選択）
	 * @return
	 */
	private JMenuItem getMntmSaveAsSelected() {
		if (mntmSaveAsSelected == null) {
			mntmSaveAsSelected = new JMenuItem("Save as (selected channels)");
			mntmSaveAsSelected.setIcon(new ImageIcon(DialogChannelDisplayProperty.class.getResource("/images/folder_classic_down.png")));
			mntmSaveAsSelected.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent arg0) {
					saveAs(false);
				}
			});
		}
		return mntmSaveAsSelected;
	}
	/**
	 * 
	 * @return
	 */
	private JMenuItem getMntmMenuItemClear() {
		if (mntmMenuItemClear == null) {
			mntmMenuItemClear = new JMenuItem("Clear");
			mntmMenuItemClear.setIcon(new ImageIcon(DialogChannelDisplayProperty.class.getResource("/images/trashcan.png")));
			mntmMenuItemClear.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent arg0) {
					clearTable(true);
				}
			});
		}
		return mntmMenuItemClear;
	}
	/**
	 * 
	 * @return
	 */
	private JMenu getMnData() {
		if (mnData == null) {
			mnData = new JMenu("Data");
			mnData.setIcon(new ImageIcon(DialogChannelDisplayProperty.class.getResource("/images/database_go.png")));
			mnData.setMargin(new Insets(0, 10, 0, 10));
			mnData.setMnemonic('D');
			mnData.add(getMnMenuDisplay());
			mnData.add(getMnPhysicalQuantitiy());
			mnData.add(getMnMask());
			mnData.add(getMnSpecialPattern());
			mnData.add(getMnInsertNew());
		}
		return mnData;
	}
	/**
	 * 
	 * @return
	 */
	private JMenu getMnMenuDisplay() {
		if (mnMenuDisplay == null) {
			mnMenuDisplay = new JMenu("Display");
			mnMenuDisplay.setIcon(new ImageIcon(DialogChannelDisplayProperty.class.getResource("/images/monitor.png")));
			mnMenuDisplay.setMnemonic('D');
			mnMenuDisplay.add(getMnDisplaySetAll());
			mnMenuDisplay.add(getMnDisplayResetAll());
		}
		return mnMenuDisplay;
	}
	private JMenuItem getMnDisplaySetAll() {
		if (mnDisplaySetAll == null) {
			mnDisplaySetAll = new JMenuItem("Set all");
			mnDisplaySetAll.setIcon(new ImageIcon(DialogChannelDisplayProperty.class.getResource("/images/checkbox.gif")));
			mnDisplaySetAll.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent arg0) {
					setAllItemSet(true,"Display");
				}
			});
		}
		return mnDisplaySetAll;
	}
	private JMenuItem getMnDisplayResetAll() {
		if (mnDisplayResetAll == null) {
			mnDisplayResetAll = new JMenuItem("Reset all");
			mnDisplayResetAll.setIcon(new ImageIcon(DialogChannelDisplayProperty.class.getResource("/images/unchecked.gif")));
			mnDisplayResetAll.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					setAllItemSet(false,"Display");
				}
			});
		}
		return mnDisplayResetAll;
	}
	private JMenu getMnPhysicalQuantitiy() {
		if (mnPhysicalQuantitiy == null) {
			mnPhysicalQuantitiy = new JMenu("Physical Quantitiy");
			mnPhysicalQuantitiy.setIcon(new ImageIcon(DialogChannelDisplayProperty.class.getResource("/images/m-s.png")));
			mnPhysicalQuantitiy.setMnemonic('P');
			mnPhysicalQuantitiy.add(getMnPQSetAll());
			mnPhysicalQuantitiy.add(getMnPQResetAll());
		}
		return mnPhysicalQuantitiy;
	}
	private JMenuItem getMnPQSetAll() {
		if (mnPQSetAll == null) {
			mnPQSetAll = new JMenuItem("Set all");
			mnPQSetAll.setIcon(new ImageIcon(DialogChannelDisplayProperty.class.getResource("/images/checkbox.gif")));
			mnPQSetAll.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					setAllItemSet(true,"PhysicalQuantity");
				}
			});
		}
		return mnPQSetAll;
	}
	private JMenuItem getMnPQResetAll() {
		if (mnPQResetAll == null) {
			mnPQResetAll = new JMenuItem("Reset all");
			mnPQResetAll.setIcon(new ImageIcon(DialogChannelDisplayProperty.class.getResource("/images/unchecked.gif")));
			mnPQResetAll.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					setAllItemSet(false,"PhysicalQuantity");
				}
			});
		}
		return mnPQResetAll;
	}
	private JMenu getMnMask() {
		if (mnMask == null) {
			mnMask = new JMenu("Mask");
			mnMask.setMnemonic('M');
			mnMask.add(getMnMaskSetAll());
			mnMask.add(getMnMaskResetAll());
		}
		return mnMask;
	}
	private JMenuItem getMnMaskSetAll() {
		if (mnMaskSetAll == null) {
			mnMaskSetAll = new JMenuItem("Set all");
			mnMaskSetAll.setIcon(new ImageIcon(DialogChannelDisplayProperty.class.getResource("/images/checkbox.gif")));
			mnMaskSetAll.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					setAllItemSet(true,"Mask");
				}
			});
		}
		return mnMaskSetAll;
	}
	private JMenuItem getMnMaskResetAll() {
		if (mnMaskResetAll == null) {
			mnMaskResetAll = new JMenuItem("Reset all");
			mnMaskResetAll.setIcon(new ImageIcon(DialogChannelDisplayProperty.class.getResource("/images/unchecked.gif")));
			mnMaskResetAll.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					setAllItemSet(false,"Mask");
				}
			});
		}
		return mnMaskResetAll;
	}
	private JMenuItem getMnSpecialPattern() {
		if (mnSpecialPattern == null) {
			mnSpecialPattern = new JMenuItem("Special Pattern");
			mnSpecialPattern.setIcon(new ImageIcon(DialogChannelDisplayProperty.class.getResource("/images/star_boxed_full.png")));
			mnSpecialPattern.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent e) {
				}
			});
		}
		return mnSpecialPattern;
	}
	private JMenuItem getMntmImportWinChannel() {
		if (mntmImportWinChannel == null) {
			mntmImportWinChannel = new JMenuItem("Import win channel file");
			mntmImportWinChannel.setIcon(new ImageIcon(DialogChannelDisplayProperty.class.getResource("/images/folder_classic_up.png")));
			mntmImportWinChannel.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					File file = chooseChannelTableFile();//@
					if(file != null) readChannelTable(file);//@
				}
			});
		}
		return mntmImportWinChannel;
	}
	private JMenuItem getMnInsertNew() {
		if (mnInsertNew == null) {
			mnInsertNew = new JMenuItem("Insert new");
			mnInsertNew.setIcon(new ImageIcon(DialogChannelDisplayProperty.class.getResource("/images/text_padding_bottom.png")));
			mnInsertNew.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					insertNewLine();
				}

			});
		}
		return mnInsertNew;
	}
	
	private void insertNewLine() {
		int idx = getMaxIndex();
		int ch = getUnUsedCh();
		if(ch>=0){
			addRow(idx+1,ch,"HAKUSAN","UD",false,false,0,9.539399e-04,"gal",8388608,false,35.674843,139.471499,100);
			// TODO 追加された行をハイライトしたい
//			jTableDisplayProperty.setRowSelectionAllowed(true);　//うまくゆかない
//			jTableDisplayProperty.setRowSelectionInterval(0,2);　//うまくゆかない
			scrollLast();
		}
	}
	/**
	 * 最後の行を表示する。
	 * ディレイした後に垂直スクロールバーを取得して最大値にセットする。
	 */
	private void scrollLast() {
		SwingUtilities.invokeLater(new Runnable() {
			@Override
			public void run() {
				JScrollBar scrollBar = jScrollPaneTable.getVerticalScrollBar();
				scrollBar.setValue(scrollBar.getMaximum());
				//jTableDisplayProperty.setRowSelectionInterval(0,10);
			}
		});
	}
	private JPanel getPanel() {
		if (panel == null) {
			panel = new JPanel();
			panel.setLayout(new BorderLayout(0, 0));
			
			JPanel panel_1 = new JPanel();
			panel_1.setAlignmentY(Component.TOP_ALIGNMENT);
			panel_1.setAlignmentX(Component.RIGHT_ALIGNMENT);
			panel.add(panel_1, BorderLayout.EAST);
			
			JLabel lblNewLabel = new JLabel("Calculator");
			lblNewLabel.setIcon(new ImageIcon(DialogChannelDisplayProperty.class.getResource("/images/calculator.png")));
			panel_1.add(lblNewLabel);
			panel_1.add(getJTextFieldCalculator());
		}
		return panel;
	}
}  //  @jve:decl-index=0:visual-constraint="10,10"
